import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Input, Select, Button } from 'antd';
import _ from 'lodash';
import sdk from '../../utils/imSdk';
import ChatItem from '../../components/ChatItem';
import UploadModal from '../../components/UploadModal';
import styles from './index.module.less';
import CommonLangModal from './commonLangModal';
import projectServer from '../../services/project';
import isSuccess from '../../utils/error';
import config from '../../config';

const { Option } = Select;
const { baseUrl } = config;
const { exportProjectStageFile } = projectServer;

/**
 * 
 * @param {原生Dom节点} f 
 * @param {插入的字符串} value 
 * @return {返回新的value}
 */
function insertAtCursor(field, value) {
    let newValue = '';
    const startPos = field.selectionStart;
    const endPos = field.selectionEnd;
    const restoreTop = field.scrollTop;
    newValue = field.value.substring(0, startPos) + value + field.value.substring(endPos, field.value.length);
    if (restoreTop > 0) {
        field.scrollTop = restoreTop;
    }
    field.focus();
    // 重新设置光标的位置, 由于react的setState为异步所以用setTimeout
    setTimeout(() => {
        field.selectionStart = startPos + value.length
        field.selectionEnd = startPos + value.length
    }, 0)
    return newValue;
}

function getCursorPre(field) {
    const startPos = field.selectionStart;
    const value = field.value;
    if (value) {
        return value[startPos - 1];
    };
}

function getIndex(str, letter = '@') {
    let index;
    for (let i = 0; i < str.length; i++) {
        if (str[i] === letter) {
            index = i;
            break;
        };
    }
    return index;
}

function creatTextMsg(text) {
    return {
        content: { text },
        type: 'TIMTextElem'
    }
}

function creatCustomMsg(data, desc) {
    return {
        content: {
            data: JSON.stringify(data),
            desc,
            ext: ''
        },
        type: 'TIMCustomElem'
    }
}

function handleStr(s, values) {
    const matchStrObj = values.reduce((pre, v) => {
        const obj = { ...pre, [`@${v.username}`]: { userid: v.userid, username: v.username } };
        return obj;
    }, {});
    const matchStrArr = Object.keys(matchStrObj);
    const str = s.replace(/@ /g, '@').replace(/^\s*|\s*$/g, '');
    const messageArr = [];
    function sortMessageList(str) {
        if (!str) return;
        else if (str.length === 1) {
            messageArr.push(creatTextMsg(str));
            return;
        }

        const idx = getIndex(str);
        if (!idx && idx !== 0) {
            messageArr.push(creatTextMsg(str));
            return;
        }
        const preText = str.substring(0, idx);
        if (preText) { // 如果前面有值的话肯定是字符串类型
            messageArr.push(creatTextMsg(preText));
        }
        const restStr = str.substring(idx);
        let descLength;
        for (let i = 0; i < matchStrArr.length; i++) {
            if (restStr.indexOf(matchStrArr[i]) === 0) {
                descLength = matchStrArr[i].length;
                const data = {
                    atlist: [matchStrObj[matchStrArr[i]]],
                    type: 'at'
                }
                messageArr.push(creatCustomMsg(data, matchStrArr[i]));
                break;
            }
        }
        if (!descLength) { // str = @@shkhkk || @sdkfhskd@khk
            const nextIdx = getIndex(restStr.substring(1));
            if (!nextIdx && nextIdx !== 0) {
                messageArr.push(creatTextMsg(restStr));
                return;
            }
            descLength = 1 + nextIdx;
            messageArr.push(creatTextMsg(restStr.substring(0, descLength)));
        }
        const remainStr = str.substring(idx + descLength);
        sortMessageList(remainStr);
    }
    sortMessageList(str);

    // 合并连续的文本类型
    const newMessageArr = messageArr.reduce((preArr, m) => {
        const pre = preArr.concat().pop();
        if (pre) {
            if (m.type === 'TIMTextElem' && pre.type === 'TIMTextElem') {
                const obj = creatTextMsg(pre.content.text + m.content.text);
                const arr = preArr.slice(0, preArr.length - 1);
                return [...arr, obj];
            } else return [...preArr, m];
        } else return [m]
    }, []);

    return newMessageArr;
}


class ChatContent extends Component {
    constructor(props) {
        super(props);
        const { chatId, chatDraftCache } = props;
        this.state = {
            value: chatDraftCache[chatId] || '', // 默认为暂存值
            showModal: false,
            groupUsersList: []
        }
    }

    componentDidMount() {
        this.needHidden = true;
        sdk.getGroupMembers({ GroupId: this.props.chatId }, (groupUsersList) => {
            if (groupUsersList.length) {
                this.setState({ groupUsersList });
            }
        });
    }

    componentWillReceiveProps(nextProps) {
        if (!this.scroll || !nextProps.data.length) return;

        if (this.needHidden) {
            this.scroll.style.visibility = 'hidden'; // 避免滚动的那一下卡顿
        }

        setTimeout(() => {
            if (this.scroll) {
                this.scroll.scrollTop = this.scroll.scrollHeight;
                this.scroll.style.visibility = 'visible';
                this.needHidden = false;
            }
        }, 200);
    }

    setMsgValue = (value) => {
        const { chatId, setChatDraftCache } = this.props;
        // 同步输入内容到缓存
        setChatDraftCache(chatId, value);
        this.setState({ value });
    }

    onChange = (e) => {
        this.setMsgValue(e.target.value);
    }

    onKeyDown = (e) => { // 实现enter发送， ctrl+enter换行
        if (e.keyCode === 13 && e.ctrlKey) {
            this.setMsgValue(this.state.value + "\n");
        }
        if (e.keyCode === 13 && !e.ctrlKey) {
            // 避免回车键换行
            e.preventDefault();
            this.sendMsg(e.target.value)
        }
    }

    onKeyUp = (e) => {
        if (!this.state.groupUsersList.length || (e.target.value === this.cacheValue)) return;
        this.cacheValue = e.target.value;
        const preLetter = getCursorPre(e.target);
        if (preLetter === '@') {
            this.setState({ showSelect: true });
        } else if (this.state.showSelect) {
            this.setState({ showSelect: false });
        }

    }

    handleSelect = (v) => {
        const newValue = insertAtCursor(ReactDOM.findDOMNode(this.area), `${v.label} `);
        this.setMsgValue(newValue);
        this.setState({ showSelect: false });
    }

    sendMsg = (value) => {
        if (!value) return;
        const { groupUsersList } = this.state;
        const has = value.match(/@/);
        // 有@的处理逻辑
        if (has && groupUsersList.length) {
            const messageArr = handleStr(value, groupUsersList);
            console.log('--messageArr--', messageArr);
            sdk.sendCustomMsg(messageArr, () => {
                this.setState({ showSelect: false });
                this.setMsgValue('');
            });
            return;
        }
        sdk.sendMsg(value, () => {
            this.setMsgValue('');
        });
    }

    onContextMenu = () => {
        const { ipcRenderer } = window.electron;
        ipcRenderer.send('show-right-click-menu', { show: ['copy', 'paste'] });
    }

    onUploadResult = (allRes, callback) => {
        callback();
    }

    showCommon = () => {
        this.setState({ showCommonModal: true });
    }

    onCommonOk = (text) => {
        this.setMsgValue(text);
    }

    onExport = async () => {
        const { exportLoading } = this.state;
        if (exportLoading) return;
        this.setState({ exportLoading: true });
        const { chatListCurrentItem } = this.props;
        const projectid = _.get(chatListCurrentItem, 'projectid');
        const stageid = _.get(chatListCurrentItem, 'stageid');
        const res = await exportProjectStageFile({ projectid, stageid });
        this.setState({ exportLoading: false });
        if (isSuccess(res)) {
            const { filename, fileid } = res.data;
            const ext = filename.split('.')[1];
            const { ipcRenderer } = window.electron;
            ipcRenderer.send('download', { files: [{ filename, url: `${baseUrl}/file/${fileid}.${ext}` }] });
        }
    }

    render() {
        const { data, chatListCurrentItem, userInfo } = this.props;
        const { value, showModal, showCommonModal, groupUsersList, showSelect, exportLoading } = this.state;
        const isavtive = _.get(chatListCurrentItem, 'group.isavtive');

        const projectid = _.get(chatListCurrentItem, 'projectid');
        const projecttype = _.get(chatListCurrentItem, 'group.projecttype');
        const stageid = _.get(chatListCurrentItem, 'stageid');

        const taskid = _.get(chatListCurrentItem, 'group.objectid');
        const isLvXie = _.get(chatListCurrentItem, 'group.groupname') === '律师协作团队';
        const isWeiXie = _.get(chatListCurrentItem, 'group.groupname') === '委托人协作团队';
        const showCommonLang = userInfo.title !== '0' && projectid && !isWeiXie;
        return (
            <>
                <div className={styles.chatScroll} ref={d => this.scroll = d}>
                    {data.map(m => (
                        <ChatItem
                            key={m.uniqueId || m.recid}
                            data={m}
                            isProject={!!projectid}
                            projectid={projectid}
                            taskid={taskid}
                        ></ChatItem>
                    ))}
                </div>
                {isavtive ? (
                    <div className={styles.inputContent}>
                        <div className={styles.inputHeader}>
                            <Button icon="file" onClick={() => this.setState({ showModal: true })} title="上传文件" />
                            {!!projectid && isLvXie ? <Button icon="cloud-download" loading={exportLoading} onClick={this.onExport} title="导出工作报告" /> : null}
                            <UploadModal
                                key={`${projectid}-${stageid}-${taskid}`}
                                type={projectid ? '1' : '2'}
                                projectid={projectid}
                                projecttype={projecttype}
                                stageid={stageid}
                                taskid={taskid}
                                show={showModal}
                                onUploadResult={this.onUploadResult}
                                onCancel={() => this.setState({ showModal: false })}
                            />
                            <div className={styles.right}>
                                {showSelect && (
                                    <Select
                                        open
                                        labelInValue
                                        className={styles.select}
                                        onChange={this.handleSelect}
                                    >
                                        {groupUsersList.map(g => (
                                            <Option value={g.userid} key={g.userid}>
                                                {g.username}
                                            </Option>
                                        ))}
                                    </Select>
                                )}

                                <div className={styles.tips}>文字输入换行（Ctrl+Enter)</div>
                                {showCommonLang && <Button className={styles.commonBtn} onClick={this.showCommon}>常用语</Button>}
                            </div>
                            {showCommonLang && (
                                <CommonLangModal
                                    title={'常用语'}
                                    visible={showCommonModal}
                                    onOk={this.onCommonOk}
                                    onCancel={() => this.setState({ showCommonModal: false })}
                                />
                            )}
                        </div>
                        <div className={styles.wrapInput}>
                            <Input.TextArea
                                ref={d => this.area = d}
                                rows={4}
                                value={value}
                                onChange={this.onChange}
                                onKeyUp={this.onKeyUp}
                                onKeyDown={this.onKeyDown}
                                onContextMenu={this.onContextMenu}
                            />
                        </div>
                        <Button
                            className={styles.send}
                            disabled={!value}
                            onClick={() => this.sendMsg(value)}
                        >
                            发送
                        </Button>
                    </div>
                ) : null}
            </>
        );
    }
}

export default ChatContent